<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <input type="file" class="file-inp" />
    <div class="container">
      <button class="file-btn">选择本地文件</button>
      <div class="prew-wraper">
        <div class="img-wraper">
          <img src="" alt="" class="preview" />
          <div class="split"></div>
        </div>
      </div>
      <div class="line"></div>
      <div class="result">
        <img src="" alt="" />
      </div>
    </div>

    <script>
      const inp = document.querySelector(".file-inp");
      const fileBtn = document.querySelector(".file-btn");
      const preview = document.querySelector(".preview");
      const prewWraper = document.querySelector(".prew-wraper");

      const containerEl = document.querySelector(".img-wraper");
      const splitEl = document.querySelector(".split");

      const resultImg = document.querySelector(".result img");

      // 当点击按钮时触发input的点击事件
      fileBtn.onclick = () => {
        inp.click();
      };

      // 选择文件
      inp.onchange = function (e) {
        const file = e.target.files[0];

        const fileReader = new FileReader();

        fileReader.onload = function (e) {
          const dataUrl = e.target.result;
          preview.src = dataUrl;

          prewWraper.style.display = "flex";
          fileBtn.style.display = "none";
        };

        fileReader.readAsDataURL(file);
      };

      // 重新设置图片的几何信息
      const previewInfo = {
        w: 0, // 实际宽
        h: 0, // 实际高
        cw: 0, // 经过css作用后的宽
        ch: 0, // 经过css作用后的高
      };
      preview.onload = function () {
        previewInfo.w = preview.naturalWidth;
        previewInfo.h = preview.naturalHeight;
        previewInfo.cw = preview.width;
        previewInfo.ch = preview.height;

        const rect = containerEl.getBoundingClientRect();
        containerInfo.h = containerEl.offsetHeight;
        containerInfo.w = containerEl.offsetWidth;
        containerInfo.x = rect.x;
        containerInfo.y = rect.y;
        maxLeft = containerInfo.w - splitEl.offsetWidth;
        maxTop = containerInfo.h - splitEl.offsetHeight;

        const splitInfo = getSplitInfo();
        const dataUrl = getSplitImageDataUrl(splitInfo);
        resultImg.src = dataUrl;
      };

      // 方块拖动

      // 图片容器的几何信息
      const containerInfo = {
        x: containerEl.offsetLeft,
        y: containerEl.offsetTop,
        w: containerEl.offsetWidth,
        h: containerEl.offsetHeight,
      };

      // 小方块边界值
      let maxLeft = containerInfo.w - splitEl.offsetWidth;
      let maxTop = containerInfo.h - splitEl.offsetHeight;

      splitEl.onmousedown = function (e) {
        const offsetInfo = {
          x: e.offsetX,
          y: e.offsetY,
        };

        containerEl.onmousemove = function (ev) {
          let left = ev.x - offsetInfo.x - containerInfo.x;
          let top = ev.y - offsetInfo.y - containerInfo.y;

          if (left <= 0) {
            left = 0;
          }
          if (left >= maxLeft) {
            left = maxLeft;
          }

          if (top <= 0) {
            top = 0;
          }
          if (top >= maxTop) {
            top = maxTop;
          }

          splitEl.style.left = left + "px";
          splitEl.style.top = top + "px";

          const splitInfo = getSplitInfo();
          const dataUrl = getSplitImageDataUrl(splitInfo);
          resultImg.src = dataUrl;
        };

        document.onmouseup = function () {
          containerEl.onmousemove = null;
          // 从这里可以拿到文件对象，然后做上传的操作
          cavs.toBlob(getFile);
        };
      };

      // 获取方块信息
      function getSplitInfo() {
        return {
          x: splitEl.offsetLeft,
          y: splitEl.offsetTop,
          w: splitEl.offsetWidth,
          h: splitEl.offsetHeight,
        };
      }

      // 获取dataUrl
      var cavs = null;
      function getSplitImageDataUrl(splitInfo) {
        const canvas = document.createElement("canvas");
        const ctx = canvas.getContext("2d");
        canvas.width = splitInfo.w;
        canvas.height = splitInfo.h;

        // 获取宽高缩放比例
        const xRadio = previewInfo.w / previewInfo.cw;
        const yRadio = previewInfo.h / previewInfo.ch;

        ctx.drawImage(
          preview,
          splitInfo.x * xRadio,
          splitInfo.y * yRadio,
          splitInfo.w * xRadio,
          splitInfo.h * yRadio,
          0,
          0,
          splitInfo.w,
          splitInfo.h
        );
        cavs = canvas;
        return canvas.toDataURL("images/png");
      }

      // canvas保存为文件对象
      function getFile(blob) {
        let file = new File([blob], "image.png", { type: "image/png" });

        console.log(file);
      }
    </script>
  </body>
</html>
